package cn.rhzz.restore;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import cn.rhzz.restore.SSLSocketClient;

public class HttpUtils {

	public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
	private static volatile OkHttpClient httpClient = null;
	private final Logger logger = LoggerFactory.getLogger(HttpUtils.class);

	public HttpUtils() {
		init();
	}

	public static void init() {
		if (httpClient == null) {
			synchronized (OkHttpClient.class) {
				if (httpClient == null) {
					httpClient = new OkHttpClient().newBuilder().cookieJar(new CookieJar() {
						private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();

						@Override
						public void saveFromResponse(HttpUrl httpUrl, List<Cookie> cookies) {
							cookieStore.put(httpUrl.host(), cookies);
						}

						@Override
						public List<Cookie> loadForRequest(HttpUrl httpUrl) {
							List<Cookie> cookies = cookieStore.get(httpUrl.host());
							return cookies != null ? cookies : new ArrayList<Cookie>();
						}
					}).connectTimeout(60, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS)
							.writeTimeout(60, TimeUnit.SECONDS).sslSocketFactory(SSLSocketClient.getSSLSocketFactory())
							.hostnameVerifier(SSLSocketClient.getHostnameVerifier()).build();
				}
			}
		}
	}

	public String post(String url, FormBody.Builder reqBody) throws IOException {
		Request request = new Request.Builder().url(url).post(reqBody.build()).build();
		try (Response response = httpClient.newCall(request).execute()) {
			return response.body().string();
		}
	}

	public String get(HttpUrl.Builder reqBody) throws IOException {
		Request request = new Request.Builder().url(reqBody.build()).build();
		try (Response response = httpClient.newCall(request).execute()) {
			return response.body().string();
		}
	}

	public void downloadFile(HttpUrl.Builder reqBody, String filepash, String filename)
			throws IOException {
		Request request = new Request.Builder().url(reqBody.build()).build();
		Call call = httpClient.newCall(request);
		call.enqueue(new Callback() {

			@Override
			public void onFailure(Call call, IOException e) {
				logger.error("Error download file: " + e.getMessage());
			}

			@Override
			public void onResponse(Call call, Response response) throws IOException {

				InputStream is = null;
				FileOutputStream fos = null;
				try {
					is = response.body().byteStream();

					int len = 0;
					File file = new File(filepash);
					if (!file.exists()) {
						boolean isOk = file.mkdirs();
						if (!isOk) {
							logger.error("Error Failed to create directory");
						}else {
							file = new File(file.toString(), filename);
						}
					} else {
						file = new File(filepash, filename);
					}
					fos = new FileOutputStream(file);
					byte[] buf = new byte[128];

					while ((len = is.read(buf)) != -1) {
						fos.write(buf, 0, len);
					}
					fos.flush();

				} catch (Exception e) {
					logger.error("Error write file: " + e.getMessage());
				} finally {
					if (is != null) {
						is.close();
					}
					if (fos != null) {
						fos.close();
					}
				}

			}

		});
	}

	public FormBody.Builder getUserLoginBody(String username, String password) throws IOException {
		FormBody.Builder params = new FormBody.Builder();
		params.add("username", username).add("password", password).add("remember", "N");

		return params;
	}

	public HttpUrl.Builder getFileListBody(String url, String sk, String sv, String pn, String ps) throws IOException {
		HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
		urlBuilder.addQueryParameter("sk", sk).addQueryParameter("sv", sv).addQueryParameter("pn", pn)
				.addQueryParameter("ps", ps);

		return urlBuilder;
	}

	public HttpUrl.Builder getDownloadFileBody(String url, String id) throws IOException {
		HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
		urlBuilder.addQueryParameter("file_id", id);

		return urlBuilder;
	}

}